#pragma once
#include "Common.hpp"
#include "Log.hpp"
#include "InetAddr.hpp"
//#include "ThreadPool.hpp"
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>

// 服务器往往是禁止拷贝的
using namespace LogModule;
using namespace ThreadPoolModule;

// using task_t = std::function<void()>;
using func_t = std::function<std::string(const std::string&, InetAddr &)>;

const static int defaultsockfd = -1;
const static int backlog = 8;

class TcpServer : public NoCopy
{
public: 
    TcpServer(func_t func, uint port) :_port(port), _listensockfd(defaultsockfd), _isrunning(false), _func(func)
    {}

    void Init()
    {
        //1.创建套接字
        _listensockfd = socket(AF_INET, SOCK_STREAM, 0);
        if(_listensockfd < 0)
        {
            LOG(LogLevel::FATAL) << "socket error";
            exit(SOCKET_ERR);
        }
        LOG(LogLevel::DEBUG) << "socket success, socketfd: " << _listensockfd;

        //2.bind端口号
        InetAddr local(_port);//通过主机转网络，利用InetAddr的接口可实现数据转变
        int n = bind(_listensockfd, local.NetAddrPtr(), local.NetAddrLen());
        if(n < 0)
        {
            LOG(LogLevel::FATAL) << "bind error";
            exit(BIND_ERR);
        }
        LOG(LogLevel::DEBUG) << "bind success, sockfd: " << _listensockfd;

        //3.设计socket状态为listen
        n = listen(_listensockfd, backlog);
        if(n < 0)
        {
            LOG(LogLevel::FATAL) << "listen error";
            exit(LISTEN_ERR);
        }
        LOG(LogLevel::DEBUG) << "listen success, sockfd; " << _listensockfd;
    }

    class ThreadData
    {
    public:
        ThreadData()
        {}
    public:
        int sockfd;
        InetAddr addr;
        TcpServer* tsvr;
    };

    // 短服务
    // 长服务: 多进程多线程比较合适
    void Server(int sockfd, InetAddr& peer)
    {
        char buffer[1024];
        while(true)
        {
            // 1. 先读取数据
            // a. n>0: 读取成功
            // b. n<0: 读取失败
            // c. n==0: 对端把链接关闭了，读到了文件的结尾 --- pipe
            ssize_t n = read(sockfd, buffer, sizeof(buffer) - 1);
            if(n > 0)
            {
                //写回数据
                std::string echo_string = "echo# ";
                echo_string += buffer;

                write(sockfd, echo_string.c_str(), echo_string.size());
            }
            else if(n == 0)
            {
                LOG(LogLevel::DEBUG) << peer.StringAddr() << " 退出了...";
                close(sockfd);
                break;
            }
            else
            {
                LOG(LogLevel::DEBUG) << peer.StringAddr() << " 异常...";
                close(sockfd);
                break;
            }
        }
    }
    static void* Routine(void *args)
    {
        //回调函数, 执行任务


    }

    void run()
    {
        _isrunning = true;
        while(_isrunning)
        {
            //a.获取连接
            struct sockaddr_in peer;//从客户端传来的套接字信息
            socklen_t len = sizeof(peer);
            //如果没有连接，accept就会阻塞
            int sockfd = accept(_listensockfd, CONV(peer), &len);
            if(sockfd < 0)
            {
                LOG(LogLevel::FATAL) << "accept error";
                exit(ACC_ERR);
            }
            InetAddr addr(peer);
            LOG(LogLevel::INFO) << "accept success, peer addr : " << addr.StringAddr();

            //version1: multiprocessing
            pid_t id = fork();
            if(id < 0)
            {
                LOG(LogLevel::FATAL) << "Fork Error";
                exit(FORK_ERR);
            }
            else if(id == 0)
            {
                //child proccess -- only service
                //不想让子进程访问listensock！
                close(_listensockfd);
                if(fork() > 0) //Fork again, and child proccess exit, then func in grandchild
                    exit(OK);
                

                Server(sockfd, addr); // GrandChild -> Orphan proccess, use OS to reap it 
                exit(OK);
            }
            else
            {
                //Parent Proccess - only listen
                close(sockfd);

                //wait the child proccess, prevent to be the "zombie"
                pid_t rid = waitpid(id, nullptr, 0);
                (void)rid;
            }

        }
    }
private:
    uint16_t _port;
    int _listensockfd; // 监听socket
    bool _isrunning;

    func_t _func; // 设置回调处理

};